package org.netty.framework.core.annotation;

import java.lang.reflect.Method;

import org.netty.framework.core.codec.CustomMsg;
import org.netty.framework.core.codec.CustomMsgDecoder;
import org.netty.framework.core.util.AnnotationContainer;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.core.type.AnnotationMetadata;

import io.netty.util.internal.StringUtil;

/**
 * 扫描自定义的注解,放到容器中
 * 
 * @author chenfanglin
 * @date 2018年10月8日下午5:54:16
 *
 */
public class AnnotationScanner {

	/**
	 * 扫描自定义的注解
	 * 
	 * @param applicationContext
	 * @param importingClassMetadata
	 * @param registry
	 */
	public void scan(ApplicationContext applicationContext, AnnotationMetadata importingClassMetadata,
			BeanDefinitionRegistry registry) {
		String[] beanNames = registry.getBeanDefinitionNames();
		for (String beanName : beanNames) {
			String startAppName = importingClassMetadata.getClassName().substring(
					importingClassMetadata.getClassName().lastIndexOf(".") + 1,
					importingClassMetadata.getClassName().length());
			if (startAppName.toLowerCase().equals(beanName.toLowerCase())) {
				continue;
			}
			Object object = applicationContext.getBean(beanName);
			scanRequestMapper(object);
			scanCmdCodec(object);
			scanCmdMapper(object);
			scanWebSocketMapper(object);
		}
	}

	/**
	 * 扫描RequestMapper
	 * 
	 * @param object
	 * @param method
	 */
	private void scanRequestMapper(Object object) {
		RequestMapper requestMapperOnClass = object.getClass().getAnnotation(RequestMapper.class);
		String baseUrl = StringUtil.EMPTY_STRING;
		if (requestMapperOnClass != null) {
			baseUrl = requestMapperOnClass.value();
		}
		Method[] methods = object.getClass().getDeclaredMethods();
		for (Method method : methods) {
			RequestMapper requestMapper = method.getAnnotation(RequestMapper.class);
			if (requestMapper != null) {
				ResponseBody responseBody = method.getAnnotation(ResponseBody.class);
				String url = requestMapper.value();
				if (responseBody != null) {
					AnnotationContainer.putHandle(baseUrl + url, new HandlerExecutionChain(object, method, true));
				} else {
					AnnotationContainer.putHandle(baseUrl + url, new HandlerExecutionChain(object, method));
				}

			}
		}
	}

	/**
	 * 扫描CmdCodec
	 * 
	 * @param object
	 */
	@SuppressWarnings("unchecked")
	private void scanCmdCodec(Object object) {
		CmdCodec cmdCodec = object.getClass().getAnnotation(CmdCodec.class);
		if (cmdCodec != null) {
			long cmd = cmdCodec.value();
			CustomMsgDecoder<CustomMsg<?>> decoder = (CustomMsgDecoder<CustomMsg<?>>) object;
			AnnotationContainer.putDecoder(cmd, decoder);
		}
	}

	/**
	 * 扫描CmdMapper
	 * 
	 * @param object
	 */
	private void scanCmdMapper(Object object) {
		Method[] methods = object.getClass().getDeclaredMethods();
		for (Method method : methods) {
			CmdMapper cmdMapper = method.getAnnotation(CmdMapper.class);
			if (cmdMapper != null) {
				long cmd = cmdMapper.value();
				AnnotationContainer.putProcess(cmd, new HandlerExecutionChain(object, method));
			}
		}
	}

	/**
	 * 扫描WebSocketMapper
	 * 
	 * @param object
	 */
	private void scanWebSocketMapper(Object object) {
		Method[] methods = object.getClass().getDeclaredMethods();
		for (Method method : methods) {
			WebSocketMapper webSocketMapper = method.getAnnotation(WebSocketMapper.class);
			if (webSocketMapper != null) {
				String url = webSocketMapper.value();
				AnnotationContainer.putWebSocketHandle(url, new HandlerExecutionChain(object, method));
			}
		}
	}
}
